home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
-
- Packet Accelerated XModem Transfer - by Tom Zerucha
- Commercial Rights Reserved
- Calibration Version
-
- ***************************************************************************/
- #include "osbind.h"
-
- /* Xmodem Character Definitions */
- #define SOH 0x01
- #define STX 0x02
- #define EOT 0x04
- #define ACK 0x06
- #define NAK 0x15
- #define CAN 0x18
-
- /* Iorec buffer */
- struct tbuf {
- char *bufp;
- int size;
- int head;
- int tail;
- int lwm;
- int hwm;
- };
-
- char inbuf[1024]; /* temp buffer */
- #define BLEN 32768L
- char getbuf[BLEN]; /* file read buffer */
-
- char ctmp[80]; /* for data conversion */
-
- /* the following three parameters control acceleration */
- int paulen; /* length of pause */
- int pauone; /* number of characters before 1st pause */
- int paudel; /* number of characters less in successive groups */
-
- long sum[ 50 ]; /* statistic buffers */
- int num[ 50 ];
-
- /*************************/
- decout( val , str )
- long val;
- char *str;
- {
- char tmp[10];
- int i;
-
- for( i = 0 ; val ; i++ ) {
- tmp[i] = ( val % 10L ) + '0';
- val /= 10L;
- }
- while( --i >= 0 )
- *str++ = tmp[i];
- *str = 0;
-
- }
-
- /*************************/
- /* calculate xymodem crc */
- /*************************/
- calccrc( str , len )
- char *str;
- int len;
- {
- int crc,i;
-
- crc = 0;
- while( --len >= 0 ) {
- crc = crc ^ (int)*str++ << 8;
- for( i = 0 ; i < 8 ; ++i )
- if( crc & 0x8000 )
- crc = crc << 1 ^ 0x1021;
- else
- crc = crc << 1;
- }
- return( crc );
- }
-
- /******************************/
- /* calculate xymodem checksum */
- /******************************/
- calccks( str , len )
- char *str;
- int len;
- {
- int cks;
-
- cks = 0;
- while( --len >= 0 ) {
- cks += *str++;
- cks &= 0xff;
- }
-
- return( cks );
-
- }
-
- /*********************************/
- /* wait for character or timeout */
- /*********************************/
- serin( dly )
- int dly;
- {
- int i;
- for( i = 0 ; i < dly*10 ; i++ ) {
- if( Bconstat(1) )
- return( Bconin(1) & 0x7f );
- p_pause( 100L );
- }
- return( -1 );
- }
-
- /**********************************/
- /* calculate and set pause values */
- /**********************************/
- setpau( pau )
- int pau;
- {
- int i,j;
-
- paulen = pau;
- /* interval of pause in characters */
- /* 3/5 - 1200 baud, 300 baud - 3/20 , 2400 baud - 6/5 , cps/200 */
- paudel = paulen * 3 / 5;
- /* number of intervals */
- pauone = 133 / paudel;
- /* round to trianglular interval: sum of i, i = 1 to n :1,3,6,10,15,21,28 */
- for( i = 55, j = 10 ; i > pauone ; i -= j-- );
- /* compute size of first exact multiple subpacket */
- pauone = j * paudel;
- /* distribute remainder equally between packets */
- pauone += ( 133 - i * paudel + j - 2 ) / j;
- /* the j - 2 forces the last packet to be 1 larger, for checksum mode
- which is 132 characters long */
- /* the speed savings is (128 - pauone + paudel) character times */
- }
-
- /***************************/
- /* send file using xymodem */
- /***************************/
- main( argc , argv )
- int argc;
- char *argv[];
- {
- long len; /* length of file */
- int crcflg; /* controls 0/1 checksum/CRC */
- int blklen; /* length of current block */
- int blkseq; /* block serial number */
- int errcnt; /* error counter */
- char *getptr; /* pointer into getbuf */
- long getcnt; /* characters remaining to send in buffer */
- int crc; /* calculated CRC of block */
- int handl; /* file handle */
- int bufflg; /* last buffer (EOF) flag */
- int redoflg; /* block was NAKed */
- struct tbuf *aob; /* I/O record for output - to tell when empty */
- int chr;
- int i;
- int tstflg;
- int tstmax;
-
- int ipau,idel;
-
- tstflg = 0;
- setpau( tstflg + 18 );
-
- tstmax = 10;
- for( i = 0 ; i < tstmax ; i++ )
- sum[i]=0,num[i]=0;
-
- /* set defaults */
- crcflg = 0; /* auto CRC */
- tstflg = 0;
-
- aob = Iorec(0) + 0x0eL; /* get RS-232 out I/O record */
-
- handl = Fopen( argv[1] , 0 ); /* open file */
- if( handl < 0 ) {
- Cconws( "OPEN FAILED\r\n" );
- return( -1 );
- }
-
- len = Fseek( 0L , handl , 2 ); /* get length - 2nd param in batch */
- Fseek( 0L , handl , 0 );
-
- bufflg = 0; /* read in first buffer */
- getcnt = Fread( handl , BLEN , getbuf );
- getptr = getbuf;
- if( getcnt < BLEN )
- bufflg = 1;
-
- while( Bconstat(1) ) /* remove extra junk */
- Bconin(1); /* line noise between eot and C */
-
- chr = 0; /* determine crc vs checksum */
- while( chr != 'C' && chr != NAK && chr != -1 )
- chr = serin( 20 );
- if( chr == -1 ) {
- Cconws( "NO START SIGNAL - SEND ABORTED\007\r\n" );
- return( -1 );
- }
-
- if( !crcflg )
- crcflg = ( chr == 'C' );
-
- blkseq = 1; /* first block number */
- redoflg = 0; /* retransmit off (for NAKs) */
-
- blklen = 128;
- errcnt = 10;
- while( --errcnt ) {
-
- sttim();
- Bconout( 1 , SOH );
- Bconout( 1 , blkseq & 0xff );
- Bconout( 1 , 255 - ( blkseq & 0xff ) );
-
- if( !redoflg ) { /* copy buffered file to xfer area */
- for( i = 0 ; i < blklen ; i++ ) {
- if( getcnt ) {
- inbuf[i] = *getptr++;
- getcnt--;
- }
- else
- inbuf[i] = 0;
- }
- }
-
- /* compute countdown before first pause */
- /*P*/ idel = 0;
- ipau = -3; /* SOH bkn bkn */
- ipau += pauone - paudel * idel++;
-
- for( i = 0 ; i < blklen ; i++ ) { /* send block */
- Bconout( 1 , inbuf[i] );
-
- /*P*/ if( i == ipau ) {
- /* compute next pause position */
- ipau += pauone - paudel * idel++;
- /* wait until send buffer empty */
- while( aob->head != aob->tail )
- ;
- /* pause for .1 +/- ? seconds */
- p_pause( (long)(paulen*5) );
- }
- }
-
- if( crcflg & 1 ) { /* send CRC or checksum */
- crc = calccrc( inbuf , blklen ); /* calculate CRC */
- Bconout( 1 , crc >> 8 );
- Bconout( 1 , crc & 0xff );
- }
- else {
- Bconout( 1 , calccks( inbuf , blklen ) );
- }
-
- if( !getcnt && !bufflg ) { /* get another send buffer */
- getcnt = Fread( handl , BLEN , getbuf );
- getptr = getbuf;
- if( getcnt < BLEN )
- bufflg = 1;
- }
-
- redoflg = 1; /* assume NAK */
- while( 1 ) { /* wait for ACK */
- chr = serin( 15 );
- if( aob->head != aob->tail ) /* if send not done */
- continue; /* discard noise */
- if( chr == -1 ) break; /* timeout? */
- if( chr == ACK ) break; /* reject any bad chars */
- if( chr == NAK ) break;
- if( chr == CAN ) break;
- }
-
- /* calculate statistics */
- i = 25600 / gettim(); /* compute bytes per second (128 bytes) */
- decout( (long)i , ctmp ); /* 200 counts per second */
- Cconws( "[" );
- Cconws( ctmp );
- Cconws( "]" );
- sum[tstflg] += i;
- num[tstflg]++;
- tstflg++;
- if( tstflg >= tstmax ) {
- tstflg = 0;
- Cconws( "\r\n" );
- }
- setpau( tstflg + 18 ); /* change calibration */
-
- if( chr == ACK ) {
- blkseq++; /* advance */
- redoflg = 0; /* no retransmit */
- errcnt = 10; /* restore error count */
- }
-
- if( chr == CAN ) break; /* interrupt */
- if( bufflg && !getcnt && !redoflg ) /* EOF */
- break;
-
- }
-
- Fclose( handl );
- if( chr == CAN ) {
- Cconws( "SEND ABORTED BY RECEIVER\007\r\n" );
- return( -1 );
- }
-
- chr = 0; /* EOT and acknowledgement */
- while( chr != ACK && errcnt-- ) {
- Bconout( 1 , EOT );
- chr = serin( 3 );
- }
-
- /* Fatal Error */
- if( !errcnt ) {
- Bconout( 1 , CAN );
- Bconout( 1 , CAN );
- Cconws( "SEND ABORTED - TOO MANY ERRORS\007\r\n" );
- return( -1 );
- }
-
- Cconws( "SEND COMPLETED\007\r\n" );
-
- /* print out average transfer rates */
- for( tstflg = 0 ; tstflg < tstmax ; tstflg++ ) {
- decout( sum[tstflg] , ctmp );
- Cconws( "[" );
- Cconws( ctmp );
- Cconws( "] " );
- sum[tstflg]/=num[tstflg];
- }
-
- Cconws( "\r\n" );
-
- for( tstflg = 0 ; tstflg < tstmax ; tstflg++ ) {
- decout( sum[tstflg] , ctmp );
- Cconws( "[" );
- Cconws( ctmp );
- Cconws( "] " );
- sum[tstflg]/=num[tstflg];
- }
-
- Cconin();
- return( 0 );
-
- }
-